////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Application.h"
#include "Strings.h"
#include "IO/FileSystem/BinaryFile.h"

#include "Strings/str_utils.h"

#include "irrString.h"

using namespace irr;

////////////////////////////////////////////////////////////////////////////////////////////////////

CStrings::CStrings()
{
	s_nFileIndex			=	-1;
	s_nNumberOfStrings		=	0;
	s_pStringsBuffer		=	NULL;
	s_aOffsets				=	NULL;
	s_nStringsLen			=	0;

	m_pBuffer = NULL;
	m_pData = NULL;
	m_pOffsets = NULL;
	m_pMapBuffer = NULL;
}
////////////////////////////////////////////////////////////////////////////////////////////////////

CStrings::~CStrings()
{
#if defined( USE_ODS_STRING )
	FreeMemory();
#else
	ClearStringTable();
#endif

	ClearMap();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void CStrings::InitMemory( u32 buffer_size, u16 nStrings )
{
	s_nNumberOfStrings	= nStrings;
	s_pStringsBuffer	= NEW GX_CHAR[ buffer_size ];
	s_aOffsets			= NEW u32[ nStrings ];
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void CStrings::FreeMemory( )
{
	SAFE_DEL_ARRAY( s_pStringsBuffer );
	SAFE_DEL_ARRAY( s_aOffsets );

	s_nFileIndex = -1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int CStrings::LoadStringPack(CBinaryFile* pFile , CBinaryFile* pOffset)
{
	//unload everything
	FreeMemory( );
			
	s_nNumberOfStrings = pOffset->ReadS16();
	
	s_nStringsLen = pFile->getSize();	
	
	//Alloc the strings buffer
 	InitMemory( s_nStringsLen, s_nNumberOfStrings );

	if( !s_pStringsBuffer || !s_aOffsets )
		return -1;
	
	
	if( pFile->Read( s_pStringsBuffer ,  s_nStringsLen) < 0 )
		return -1;
		
	char* buffer = NEW char[s_nNumberOfStrings * 2]; 
	
	if( !buffer )
		return -1;

	if( pOffset->Read( buffer ,  s_nNumberOfStrings * 2) < 0 )
		return -1;

	s_aOffsets[0] = 0;

	for (int i = 1; i < s_nNumberOfStrings; i++)
	{
		s_aOffsets[i] = (int)(((buffer[(i-1)*2]&0xFF) + ((buffer[(i-1)*2+1]&0xFF)<<8)) / 2);
	}

	SAFE_DEL_ARRAY(buffer);

	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int CStrings::LoadStringMap(CBinaryFile* mapFile)
{
	ClearMap();

	int nNumberOfStrings = mapFile->ReadS16();

	for (int i=0; i < nNumberOfStrings; i++)
	{
		int size = mapFile->ReadS32();
		GX_CHAR* buffer = new GX_CHAR[size/2 + 1];
		buffer[size/2] = '\0';
		mapFile->read(buffer, size);
		m_strMap.push_back(buffer);
	}

	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int CStrings::GetStringIdFromName(const char* strName)
{
#if defined(USE_ODS_STRING)
	static GX_CHAR buf[256];

	for (int i=0; i < m_strMap.size(); i++)
	{
#ifdef WIN32
		if ( !wcscmp(m_strMap[i], irr::core::stringw(strName).c_str()) )
			return i;
#else
		CharToUnicode(buf, strName);
		if (!strcmp(m_strMap[i], buf))
			return i;
#endif
	}

	return -1;
#else
	for (int i=0; i < m_dataMap.size(); i++)
	{
		char *pTmp = m_dataMap[i];
		if( stricmp( pTmp, strName ) == 0 )
		{
			return i;
		}
	}
	return -1;
#endif
}

GX_CHAR* CStrings::GetString( int id )
{
#if defined(USE_ODS_STRING)
	return &s_pStringsBuffer[ s_aOffsets[ id ] ];
#else
	if( id <0 || id >= m_nStrings)
	{
#if defined(WIN32)
		return L"Wrong!!!";
#else
		static GX_CHAR buf[256];
		CharToUnicode(buf,"Wrong!!!");
		return buf;
#endif
	}
	return m_pData + (m_pOffsets[id] / 2);
#endif
}

int CStrings::LoadData(CBinaryFile* stringsFile)
{
	ClearStringTable();

	StreamSize fileSize = stringsFile->getSize();
	m_pBuffer = new irr::u8[fileSize * 2 ];
	irr::u8 *pHead =(irr::u8 *)(((u32)m_pBuffer + 3) & ~3);//Align to 4 byte

	StreamSize readSize = stringsFile->read(pHead, fileSize);
	
	if(readSize != fileSize)
	{
		ASSERT(0);
	}

	m_nStrings = *(int *)pHead;
#ifdef _DEBUG
	printf("String Loaded Number=%d\n", m_nStrings);
#endif

	m_pOffsets = (unsigned int *)(pHead + 4);
	
	u16 *pBuf16 = (u16	*)(m_pOffsets + m_nStrings);
#if defined(WIN32)
	m_pData = (wchar_t *)(pBuf16); //4 bytes align
#else
	m_pData = pBuf16;
#endif

	return 0;
}
int CStrings::LoadDataMap(CBinaryFile* mapFile)
{
	ClearMap();

	StreamSize fileSize = mapFile->getSize();
	m_pMapBuffer = new char[fileSize+1];

	StreamSize readSize = mapFile->read(m_pMapBuffer, fileSize);
	
	if(readSize != fileSize)
	{
		ASSERT(0);
	}
	m_pMapBuffer[fileSize]='\0';

	int startPos = 0;
	int pos = 0;
	char *Tmp = m_pMapBuffer;
	while( true )
	{
		if( Tmp[pos] == 0 )
		{
			char *Tmp2 = Tmp + startPos;
			if( startPos!= pos )
			{
				m_dataMap.push_back( Tmp2 );
			}
			break;
		}
		else if( Tmp[pos] == 0x0a)
		{
			Tmp[pos] = 0;
			char *Tmp2 = Tmp + startPos;
			m_dataMap.push_back( Tmp2 );
			startPos = pos+1;
		}
		pos++;
	}
	return 0;
}

void CStrings::ClearStringTable()
{
	SAFE_DEL_ARRAY(m_pBuffer);
	m_pData = NULL;
	m_pOffsets = NULL;
	m_nStrings = 0;
}

void CStrings::ClearMap()
{
#if defined( USE_ODS_STRING )
	for (int i=0; i < m_strMap.size(); i++)
	{
		SAFE_DEL(m_strMap[i]);
	}

	m_strMap.clear();
#else
	SAFE_DEL_ARRAY(m_pMapBuffer);
	m_dataMap.clear();
#endif
}

////////////////////////////////////////////////////////////////////////////////////////////////////
//
//#define LG_MAX_NO_GROUPS		5
//
//void SplitNumberInGroups( int nNumber, int* pGroups, int &nNoGroups )
//{
//
//	nNoGroups	=	0;
//
//	do
//	{
//		pGroups[ nNoGroups++ ] = nNumber % 1000;
//		nNumber /= 1000;
//	}
//	while( nNumber && nNoGroups < LG_MAX_NO_GROUPS );
//	
//
//	ASSERT( nNoGroups < LG_MAX_NO_GROUPS );
//}
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//void GetMoneyString( int nMoney, wchar_t* pBuffer , wchar_t* pPrefix , wchar_t* pSufix ) //$
//{ 
// 	int pGroups[ LG_MAX_NO_GROUPS ];
// 	int nNoGroups;		
//
//	bool neg = (nMoney < 0 );
//	
//	if (neg)
//	{
//		nMoney *= -1; 
//	}
//
// 	SplitNumberInGroups( nMoney, pGroups, nNoGroups );
// 	
// 	bool bSkipSeparator4 = FALSE;
// 	char cSeparator = ',';
// 	
//	wchar_t pTemp[64];
//	
//	if (neg)
//	{
//		GX_STRCPY(pBuffer , L"-");
//	}
//
//	if (pPrefix != NULL)
//	{
//		if (neg)
//		{	
//			GX_STRCAT(pBuffer , pPrefix);
//		}
//		else
//		{
//			GX_STRCPY(pBuffer , pPrefix);
//		}
//	}
//
// 	switch( nNoGroups )
// 	{
// 		case 1: 		
//			SPRINTF( pTemp, 64 , L"%d", pGroups[0]); 		
//		break;
// 		case 2: 
//			if( bSkipSeparator4 && pGroups[1] < 10 )
//			{
//				SPRINTF( pTemp, 64 , L"%d%03d", pGroups[1], pGroups[0]);
//			}
//			else
//			{
//				SPRINTF( pTemp,64 ,  L"%d%c%03d", pGroups[1], cSeparator, pGroups[0]);
//			}
// 		break;
//	 
// 		case 3: 
//			SPRINTF( pTemp, 64 , L"%d%c%03d%c%03d", pGroups[2], cSeparator, pGroups[1], cSeparator, pGroups[0] ); 
//		break;
// 		case 4: 
//			SPRINTF( pTemp, 64 , L"%d%c%03d%c%03d%c%03d",  pGroups[3], cSeparator, pGroups[2], cSeparator ,pGroups[1], cSeparator, pGroups[0]);
//		break;
// 		case 5: 
//			SPRINTF( pTemp, 64 , L"%d%c%03d%c%03d%c%03d%c%03d",  pGroups[4], cSeparator, pGroups[3], cSeparator, pGroups[2], cSeparator ,pGroups[1], cSeparator, pGroups[0]); 
//		break;
// 	}
//
// 	if (nNoGroups >= 1 && nNoGroups <= 5)
//	{
//		if (pPrefix)
//		{
//			GX_STRCAT(pBuffer , pTemp);
//		}
//		else
//		{
//			GX_STRCPY(pBuffer , pTemp);
//		}
//	}
//
//	if (pSufix)
//	{
//		GX_STRCAT(pBuffer , pSufix);
//	}
//
//}

////////////////////////////////////////////////////////////////////////////////////////////////////

//char* CStrings::GetDistanceString( int nTime, char* pBuffer )
//{
// 	int nLanguage = CFramework::GetInstance()->GetLanguage();
// 
// 	if( !pBuffer )
// 	{
// 		pBuffer	=	(char*)CFramework::GetInstance()->m_temporary;
// 	}
// 
// 	int pGroups[ LG_MAX_NO_GROUPS ];
// 	int nNoGroups;
// 
// 	SplitNumberInGroups( nTime, pGroups, nNoGroups );
// 
// 	bool bSkipSeparator4 = FALSE;
// 	char cSeparator;
// 	char pPrefix[4];
// 	char pSufix[4];
// 
// 	pPrefix[ 0 ]	=	0;
// 	pSufix[ 0 ]		=	0;
// 
// 	if( nLanguage == LANGUAGE_ENGLISH )
// 	{
// 		cSeparator = ',';
// 		SPRINTF( pSufix,"%cft", FONT_CH_SPACE_NOBREAK );
// 		//GX_STRCPY ( pSufix, " ft" );
// 	}
// 	else if( nLanguage == LANGUAGE_GERMAN || nLanguage == LANGUAGE_ITALIAN )
// 	{
// 		cSeparator = FONT_CH_SPACE_NOBREAK;
// 		SPRINTF( pSufix,"%cm", FONT_CH_SPACE_NOBREAK );
// 		//GX_STRCPY ( pSufix, " m" );
// 	}
// 	else if( nLanguage == LANGUAGE_SPANISH || nLanguage == LANGUAGE_FRENCH )
// 	{
// 		cSeparator = FONT_CH_SPACE_NOBREAK;
// 		SPRINTF( pSufix,"%cm", FONT_CH_SPACE_NOBREAK );
// 		//GX_STRCPY ( pSufix, " m" );
// 		bSkipSeparator4 = TRUE;
// 	}
// 
// 	switch( nNoGroups )
// 	{
// 	case 1: SPRINTF( pBuffer, "%s%d%s", 
// 				pPrefix, pGroups[0], pSufix ); break;
// 	case 2: 
// 		if( bSkipSeparator4 && pGroups[1] < 10 )
// 		{
// 			SPRINTF( pBuffer, "%s%d%03d%s",
// 				pPrefix, pGroups[1], pGroups[0], pSufix );
// 		}
// 		else
// 		{
// 			SPRINTF( pBuffer, "%s%d%c%03d%s",
// 				pPrefix, pGroups[1], cSeparator, pGroups[0], pSufix );
// 		}
// 		break;
// 
// 	case 3: SPRINTF( pBuffer, "%s%d%c%03d%c%03d%s",
// 				pPrefix, pGroups[2], cSeparator, pGroups[1], cSeparator, pGroups[0], pSufix ); break;
// 	case 4: SPRINTF( pBuffer, "%s%d%c%03d%c%03d%c%03d%s",
// 				pPrefix, pGroups[3], cSeparator, pGroups[2], cSeparator ,pGroups[1], cSeparator, pGroups[0], pPrefix ); break;
// 	case 5: SPRINTF( pBuffer, "%s%d%c%03d%c%03d%c%03d%c%03d%s",
// 				pPrefix, pGroups[4], cSeparator, pGroups[3], cSeparator, pGroups[2], cSeparator ,pGroups[1], cSeparator, pGroups[0], pPrefix ); break;
// 	}
// 
// 
// 	return pBuffer;
//	return NULL;
//}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

//#define SPECIAL_CHARS_TABLE_LENGTH		35

//char* ToUpperCase( char* str )
//{
	//disabling To UpperCase Atica's request 
// 	int len = GX_STRLEN(str);
// 
// 	for (int i=0; i< len; i++)
// 	{
// 		if ((str[i] >= 'a') && (str[i] <= 'z'))
// 		{
// 			str[i] = str[i] - ('a' - 'A');
// 		}
// 		else if (((unsigned char)str[i] >= 224) && ((unsigned char)str[i] <= 252))
// 		{
// 			str[i] = str[i] - ((char)224 - (char)192);
// 		}
// 	}

//	return str;
//}
///////////////////////////////////////////////////////////////////
//
//
/*char* Capitelize( char* str )
{
	int len = GX_STRLEN(str);
	//char[] cap = new char[len];

	bool act = TRUE; //for first letter 

	for (int i=0; i< len; i++)
	{
		if ((str[i] >= 'a') && (str[i] <= 'z') && act == TRUE)
		{
			str[i] = str[i] - ('a' - 'A');
			act = FALSE;
		}
		else if ((str[i] >= 'A') && (str[i] <= 'Z') && act == FALSE)
		{
			str[i] = str[i] + ('a' - 'A');			
		}
		else if (((unsigned char)str[i] >= 224) && ((unsigned char)str[i] <= 252))
		{
			str[i] = str[i] - ((char)224 - (char)192);
		}
		else if (act == TRUE)
		{
			act = FALSE;
		}
		else if (str[i] == ' ')
		{
			act = TRUE; //after space next simbol will be Capitalized
		}
	}

	return str;
}*/
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
